﻿using TodoApp.Application.Dtos;
using System.Linq.Expressions;
using AutoMapper; 
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

/// <summary>
/// 待办清单
/// </summary>
[Route("todo")]
public class TodoListController : ControllerBase
{
    public TodoDbContext TodoDb { get; }
    public IMapper Mapper { get; }

    // 这里DbContext 不应该直接注入进来使用。应该把业务拆到Service里，并且持久化应该有仓储。
    public TodoListController(TodoDbContext todoDb,
                              IMapper mapper)
    {
        TodoDb = todoDb;
        Mapper = mapper;
    }

    /// <summary>
    /// 添加待办
    /// </summary>
    [HttpPost]
    public async Task<TodoDto> CreateAsync(TodoCreationDto input)
    {
        {
            var todo = new Todo
            {
                Content = input.Content
            };

            await TodoDb.Todos.AddAsync(todo);
            await TodoDb.SaveChangesAsync();

            return Mapper.Map<TodoDto>(todo);
        }
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    [HttpGet]
    public async Task<PagedResult<TodoDto>> GetPagedListAsync(TodoQueryDto input)
    {
        var query = TodoDb.Todos
            .WhereIf(input.IsComplete.HasValue, t => t.IsComplete == input.IsComplete.Value)
            .WhereIf(!string.IsNullOrWhiteSpace(input.Content), t => t.Content.Contains(input.Content))
            .WhereIf(input.CompleteTimeLeft.HasValue, t => t.CompleteTime >= input.CompleteTimeLeft.Value)
            .WhereIf(input.CompleteTimeRight.HasValue, t => t.CompleteTime <= input.CompleteTimeRight.Value);

        var total = await query.CountAsync();

        var todos = await query.OrderBy(x => x.CreationTime)
            .Skip(input.Skip)
            .Take(input.Take)
            .ToListAsync();

        var items = Mapper.Map<List<TodoDto>>(todos);
        return new(total, items);
    }
    /// <summary>
    /// 更新
    /// </summary>
    [HttpPut("{id}")]
    public async Task<TodoDto> UpdateAsync(long id, TodoUpdateDto input)
    {
        var todo = await TodoDb.Todos.FindAsync(id);
        if (todo == null)
        {
            // 应该返回一个NotFound啥的。。。
            throw new Exception("Todo not found");
        }

        todo.Content = input.Content; 

        await TodoDb.SaveChangesAsync();

        return Mapper.Map<TodoDto>(todo);
    }

    /// <summary>
    /// 完成
    /// </summary>
    [HttpPut("{id}/complete")]
    public async Task CompleteAsync(long id)
    {
        var todo = await TodoDb.Todos.FirstOrDefaultAsync(t => t.Id == id);
        todo.Complete();
        await TodoDb.SaveChangesAsync();
    }

    /// <summary>
    /// 删除
    /// </summary>
    [HttpDelete("{id}")]
    public async Task DeleteAsync(long id)
    {
        var todo = await TodoDb.Todos.FirstOrDefaultAsync(t => t.Id == id);
        TodoDb.Todos.Remove(todo);
        await TodoDb.SaveChangesAsync();
    }

    /// <summary>
    ///     你好
    /// </summary>
    [HttpGet("hello")]
    public string Hello()
    {
        return "123456";
    }
}


public static class QueryableExtensions
{
    public static IQueryable<TEntity> WhereIf<TEntity>(this IQueryable<TEntity> query, bool condition, Expression<Func<TEntity, bool>> predicate)
        where TEntity : class
    => condition ? query.Where(predicate) : query;
}